<?php

use think\captcha\Captcha;
use think\Db;

// 异常错误报错级别,
error_reporting(E_ERROR | E_PARSE);

function C($name)
{
    $config = cache('systemConfig');
    if ($config) {
        $value = '';
        foreach ($config as $v) {
            if ($v['name'] == $name) {
                $value = $v['output_value'];
                break;
            }
        }
        
        return $value;
    } else {
        return Db::name('config')->where(['name' => $name])->order('sort asc')->value('value');
    }
}

/**
 * 系统加密方法
 *
 * @param    string    $data      要加密的字符串
 * @param    int       $expire    过期时间 (单位:秒)
 *
 * @return string
 */
function thinkEncrypt($data, $expire = 0)
{
    $key = md5('083d9a270e6e16b2fbb08d35067aae5f');
    $data = base64_encode($data);
    $x = 0;
    $len = strlen($data);
    $l = strlen($key);
    $char = '';
    for ($i = 0; $i < $len; $i++) {
        if ($x == $l) $x = 0;
        $char .= substr($key, $x, 1);
        $x++;
    }
    $str = sprintf('%010d', $expire ? $expire + time() : 0);
    for ($i = 0; $i < $len; $i++) {
        $str .= chr(ord(substr($data, $i, 1)) + (ord(substr($char, $i, 1))) % 256);
    }
    
    return str_replace('=', '', base64_encode($str));
}

/**
 * 系统解密方法
 *
 * @param    string    $data    要解密的字符串 （必须是think_encrypt方法加密的字符串）
 *
 * @return string
 */
function thinkDecrypt($data)
{
    $key = md5('083d9a270e6e16b2fbb08d35067aae5f');
    $x = 0;
    $data = base64_decode($data);
    $expire = substr($data, 0, 10);
    $data = substr($data, 10);
    if ($expire > 0 && $expire < time()) {
        return '';
    }
    $len = strlen($data);
    $l = strlen($key);
    $char = $str = '';
    for ($i = 0; $i < $len; $i++) {
        if ($x == $l) $x = 0;
        $char .= substr($key, $x, 1);
        $x++;
    }
    for ($i = 0; $i < $len; $i++) {
        if (ord(substr($data, $i, 1)) < ord(substr($char, $i, 1))) {
            $str .= chr((ord(substr($data, $i, 1)) + 256) - ord(substr($char, $i, 1)));
        } else {
            $str .= chr(ord(substr($data, $i, 1)) - ord(substr($char, $i, 1)));
        }
    }
    
    return base64_decode($str);
}

/**
 * 检查验证码
 * */
function checkVerify($code)
{
    $verify = new Captcha();
    
    return $verify->check($code);
}

/**
 * 判断是否SSL协议
 *
 * @return boolean
 */
function is_ssl()
{
    if (isset($_SERVER['HTTPS']) && ('1' == $_SERVER['HTTPS'] || 'on' == strtolower($_SERVER['HTTPS']))) {
        return true;
    } elseif (isset($_SERVER['SERVER_PORT']) && ('443' == $_SERVER['SERVER_PORT'])) {
        return true;
    }
    
    return false;
}

/**
 * 获取域名前缀
 * */
function getHost()
{
    $res = is_ssl();
    if ($res) {
        return 'https://' . $_SERVER['HTTP_HOST'];
    } else {
        return 'http://' . $_SERVER['HTTP_HOST'];
    }
}

/**
 * 按综合方式输出通信数据
 *
 * @param    integer    $result    状态码
 * @param    string     $msg       提示信息
 * @param    array      $data      数据
 *
 * @return string
 */
function apiReturn($result, $msg = '', $data = false)
{
    if (!is_numeric($result)) {
        return '';
    }
    
    return apiJson($result, $msg, $data);
}

/**
 * 按json方式输出通信数据
 *
 * @param    integer    $result    状态码
 * @param    string     $msg       提示信息
 * @param    array      $data      数据
 *
 * @return string
 */
function apiJson($result, $msg = '', $data = false)
{
    if (!is_numeric($result)) {
        return '';
    }
    
    if ($data > 0 || $data === []) {
        $message = array(
            'result' => $result, 'msg' => $msg, 'data' => $data ?: []
        );
    } else {
        $message = array(
            'result' => $result, 'msg' => $msg, 'data' => $data ?: ''
        );
    }
    
    echo json_encode($message, JSON_UNESCAPED_UNICODE);
    exit;
}

/**
 * 根据图片id获取图片路径
 * */
function getPicture($id)
{
    if (preg_replace('/\D/s', '', $id) == $id) {
        //ID
        $info = Db::name('picture')->field('path')->where(['id' => $id])->find();
        if ($info) {
            return getHost() . $info['path'];
        } else {
            return '';
        }
    } else {
        //路径
        return $id;
    }
}

/**
 * 用户头像处理
 *
 * @param    int    $avatar_id    用户头像ID 或 用户头像路径
 *
 * @return string
 * */
function doAvatar($avatar_id)
{
    if (strlen($avatar_id) < 10) {
        //此时用户头像为修改之后的头像
        $avatar = getPicture($avatar_id);
    } else {
        $avatar = $avatar_id;
    }
    
    return $avatar ?: '';
}

/**
 * 多图处理
 *
 * @param    string    $imgs       图片id集合
 * @param    string    $img_key    自定义图片路径下标
 *
 * @return array
 * */
function doImgs($imgs, $img_key = 'path')
{
    $new_img_arr = [];
    if ($imgs) {
        $img_arr = explode(',', $imgs);
        
        if ($img_arr) {
            foreach ($img_arr as $k => $v) {
                $new_img_arr[$k]['id'] = $v;
                $new_img_arr[$k][$img_key] = getPicture($v);
            }
        }
    }
    
    return $new_img_arr;
}

/**
 * 获取[规格-属性]数据
 *
 * @param    int    $goods_id    商品id
 *
 * @return array
 * */
function getSku($goods_id)
{
    if (!cache('sku_' . $goods_id)) {
        $sku_value_list = Db::name('sku_value')->where(['goods_id' => $goods_id])->select();
        
        //$skus_id_arr：所有属性的id集合
        $skus_id_arr = [];
        $sku_list = [];
        if ($sku_value_list) {
            foreach ($sku_value_list as &$val) {
                $val['img'] = getPicture($val['img']);
                
                $sku_id = explode('-', $val['sku_id']);
                if ($sku_id) {
                    foreach ($sku_id as $value) {
                        if (!in_array($value, $skus_id_arr)) {
                            $skus_id_arr[] = $value;
                        }
                    }
                }
            }
            
            $parent_list = Db::name('sku')->distinct(true)->field('pid')->where(['id' => ['IN', $skus_id_arr]])->select();
            $parent_ids = array_column((array)$parent_list, 'pid');
            if ($parent_ids) {
                $sku_list = Db::name('sku')->field('id,name title')->where(['id' => ['IN', $parent_ids]])->select();
                if ($sku_list) {
                    foreach ($sku_list as &$v) {
                        $child_list = Db::name('sku')->field('id,name title')->where(['pid' => $v['id']])->select();
                        if ($child_list) {
                            foreach ($child_list as &$val) {
                                $val['class'] = '';
                                $val['status'] = false;
                                foreach ($sku_value_list as $value) {
                                    if (in_array($val['id'], explode('-', $value['sku_id'])) && $value['status']) {
                                        $val['status'] = true;
                                        break;
                                    }
                                }
                            }
                        } else {
                            $child_list = [];
                        }
                        $v['child'] = $child_list;
                    }
                } else {
                    $sku_list = [];
                }
            }
        } else {
            $sku_value_list = [];
        }
        
        $data = [
            'sku_list' => $sku_list, 'sku_value_list' => $sku_value_list
        ];
        cache('sku_' . $goods_id, $data);
    } else {
        $data = cache('sku_' . $goods_id);
    }
    
    return $data;
}

/**
 * 微信违规文字检测
 * */
function checkContent($content)
{
    if ($access_token = accessToken()) {
        $checkUrl = 'https://api.weixin.qq.com/wxa/msg_sec_check?access_token=' . $access_token;
        $arr = [
            'content' => $content
        ];
        
        $result = httpRequest($checkUrl, $arr, 'json');
        $result = json_decode($result, true);
        
        if ($result['errcode'] != 0) apiReturn(2, '检测到文字含违规内容，请重新编辑');
    } else {
        apiReturn(2, 'access_token获取失败');
    }
}

function accessToken()
{
    $appid = C('XCX_APPID');
    $secret = C('XCX_SECRET');
    $tokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" . $appid . "&secret=" . $secret;
    $tokenArr = file_get_contents($tokenUrl);
    $tokenArr = json_decode($tokenArr, true);
    
    return $tokenArr['access_token'];
}

function httpRequest($url, $data, $type)
{
    if ($type == 'json') {
        $headers = array("Content-type: application/json;charset=UTF-8", "Accept: application/json", "Cache-Control: no-cache", "Pragma: no-cache");
        $data = json_encode($data, JSON_UNESCAPED_UNICODE);
    } else {
        $headers = [];
    }
    $curl = getCurl($url, $data);
    curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
    $output = curl_exec($curl);
    curl_close($curl);
    
    return $output;
}

/**
 * @param $url
 * @param $data
 *
 * @return false|resource
 */
function getCurl($url, $data)
{
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
    if (!empty($data)) {
        curl_setopt($curl, CURLOPT_POST, 1);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
    }
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
    
    return $curl;
}

/**
 * 一维数组去重
 * */
function a_array_unique($array)
{
    $out = array();
    foreach ($array as $key => $value) {
        if (!in_array($value, $out)) {
            $out[$key] = $value;
        }
    }
    
    return $out;
}

/**
 * 处理富文本信息
 *
 * @param    string    $content    富文本内容
 *
 * @return  string
 * */
function doEditorContent($content)
{
    return $content ? str_replace('<img src="', ' < img style = "width: 100%; height: auto" src = "' . getHost(), $content) : '';
}

/**
 * 格式化时间
 *
 * @param    int     $time    时间戳
 * @param    date    $date    时间格式
 * */
function timeFormat($time, $date = 'Y-m-d H:i:s')
{
    if ($time) {
        return date($date, $time);
    } else {
        return '';
    }
}

/**
 * @param    array    $sku_id    属性id集合
 *
 * @return string
 * */
function getSkuName($sku_id)
{
    if ($sku_id) {
        $in_sku = implode(',', $sku_id);
        $order = ' field (id, ' . $in_sku . ' ) ';
        $sql = 'SELECT `name` FROM `tp_sku` WHERE `id` IN(' . $in_sku . ') ORDER BY ' . $order;
        
        return Db::query($sql);
    } else {
        return '';
    }
}

/**
 * 获取省id
 *
 * @param    string    $province_name    省名称
 *
 * @return int
 * */
function getProvinceId($province_name)
{
    return Db::name('province')->where(['name' => $province_name])->value('province_id');
}

/**
 * 获取省名称
 *
 * @param    int    $province_id    省id
 *
 * @return string
 * */
function getProvinceName($province_id)
{
    $name = Db::name('province')->where(array('province_id' => $province_id))->value('name');
    
    return $name ?: '';
}

/**
 * 获取市id
 *
 * @param    string    $province_name    省名称
 * @param    string    $city_name        市名称
 *
 * @return int
 * */
function getCityId($province_name, $city_name)
{
    $province_id = getProvinceId($province_name);
    
    $city_name = str_replace(array('市', '省'), '', $city_name);
    
    return Db::name('city')->where(array('province_id' => $province_id, 'name' => array('like', $city_name . '%')))->value('city_id');
}

/**
 * 获取市名称
 *
 * @param    int    $city_id    市id
 *
 * @return string
 * */
function getCityName($city_id)
{
    $name = Db::name('city')->where(array('city_id' => $city_id))->value('name');
    
    return $name ?: '';
}

/**
 * 获取区id
 *
 * @param    string    $province_name    省名称
 * @param    string    $city_name        市名称
 * @param    string    $area_name        市名称
 *
 * @return int
 * */
function getAreaId($province_name, $city_name, $area_name)
{
    $city_id = getCityId($province_name, $city_name);
    
    $area_name = str_replace(array('市', '区', '县'), '', $area_name);
    
    return Db::name('area')->where(array('city_id' => $city_id, 'name' => array('like', $area_name . '%')))->value('area_id');
}

/**
 * 获取区名称
 *
 * @param    int    $area_id    区id
 *
 * @return string
 * */
function getAreaName($area_id)
{
    $name = Db::name('area')->where(array('area_id' => $area_id))->value('name');
    
    return $name ?: '';
}

function httpsRequest($url, $data = null)
{
    $curl = getCurl($url, $data);
    $output = curl_exec($curl);
    curl_close($curl);
    
    return $output;
}

/**
 * 获取access_token
 *
 * @param    string    $token_file_name    token存储文件名
 * @param    int       $type               1:公众号token，2：小程序token
 *
 * @return string
 *  */
function get_access_token(
    $token_file_name = 'access_token.json', $type = 1, &$count = 0
) {
    if ($type == 1) {
        $config = [
            'appid' => C('GZH_APPID'), 'secret' => C('GZH_SECRET'),
        ];
    } else {
        $config = [
            'appid' => C('XCX_APPID'), 'secret' => C('XCX_SECRET'),
        ];
    }
    
    // access_token 应该全局存储与更新，以下代码以写入到文件中做示例
    $data = json_decode(get_php_file($token_file_name));
    if ($data->expires_time < time()) {
        // 如果是企业号用以下URL获取access_token
        $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" . $config['appid'] . "&secret=" . $config['secret'];
        $access_token_json = httpsRequest($url);
        $access_token = json_decode($access_token_json, true);
        $code = $access_token['errcode'] ?: 0;
        if ($code == 0) {
            $data->expires_time = time() + 3000;
            $data->access_token = $access_token;
            set_php_file($token_file_name, json_encode($data));
            
            $access_token = $access_token['access_token'];
        } else {
            if ($count < 3) {
                ++$count;
                get_access_token($token_file_name, $type, $count);
            } else {
                unlink(RUNTIME_PATH . '/' . $token_file_name);
                apiReturn(2, $access_token['errmsg']);
            }
        }
    } else {
        $access_token = $data->access_token->access_token;
    }
    
    return $access_token;
}

function get_php_file($filename)
{
    if (!is_file(RUNTIME_PATH . '/' . $filename)) {
        $data['expires_time'] = 0;
        $data['jsapi_ticket'] = '';
        set_php_file($filename, json_encode($data));
    }
    
    return file_get_contents(RUNTIME_PATH . '/' . $filename);
}

function set_php_file($filename, $content)
{
    file_put_contents(RUNTIME_PATH . '/' . $filename, $content);
}

/**
 * 注册用户 及 绑定用户
 *
 * @param    array    $user_data    当前用户信息
 *
 * @return array
 * */
function bindUser($user_data)
{
    $time = time();
    
    $user_info = Db::name('user')->where(['openid' => $user_data['openid']])->find();
    if ($user_info) {
        // 直接返回用户id和用户手机号
        $return_data = [
            'user_id' => $user_info['id'], 'mobile' => $user_info['mobile'] ?: ''
        ];
    } else {
        // 新用户
        
        //注册用户信息 及 绑定
        $user_data['create_time'] = $time;
        
        $return_user_id = Db::name('user')->insertGetId($user_data);
        
        $return_data = [
            'user_id' => $return_user_id, 'mobile' => ''
        ];
    }
    
    return $return_data;
}

/**
 * 生成用户分享码（公众号二维码[带用户id]）
 *
 * @param    string    $user_id    用户id
 *
 * @return string
 * */
function createUserQr($user_id)
{
    $qr = Db::name('user')->where(['id' => $user_id])->value('qr');
    if ($qr == 0) {
        $access_token = get_access_token();
        
        $data = '{"action_name": "QR_LIMIT_STR_SCENE", "action_info": {"scene": {"scene_str": "' . $user_id . '"}}}';
        
        $url = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=" . $access_token;
        
        $res = httpsRequest($url, $data);
        
        $result = json_decode($res, true);
        $ticket = $result['ticket'];
        $img = file_get_contents('https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=' . $ticket);
        
        $dir = './uploads/userQr/';
        if (!is_dir($dir)) mkdir($dir);
        
        $path = $dir . 'userQr_' . $user_id . '.jpg';
        
        $data = [
            'path' => substr($path, 1), 'create_time' => time()
        ];
        $id = Db::name('picture')->insertGetId($data);
        
        if ($id) {
            file_put_contents($path, $img);
            Db::name('user')->where(['id' => $user_id])->setField('qr', $id);
        }
    }
    
    return $id ?: '';
}

/**
 * 隐藏手机号
 *
 * @param    string    $tel    手机号
 *
 * @return string
 * */
function hideMobile($tel)
{
    return $tel ? substr_replace($tel, '****', 3, 4) : '';
}

/**
 * 过滤文本中的emoji表情包（输出到excel文件中会导致问题）
 *
 * @param    string    $text    原文本
 *
 * @return string 过滤emoji表情包后的文本
 */
function removeEmoji($text)
{
    $len = mb_strlen($text);
    $newText = '';
    for ($i = 0; $i < $len; $i++) {
        $str = mb_substr($text, $i, 1, 'utf-8');
        if (strlen($str) >= 4) continue;//emoji表情为4个字节
        $newText .= $str;
    }
    
    return $newText;
}

/**
 * workerman
 * 获取后台用户列表用户最新的消息时间
 *
 * @param    int    $user_id    用户id
 *
 * @return string
 * */
function getUserNewMsgTime($user_id)
{
    $create_time = Db::name('chat')->where(['from_uid' => $user_id])->whereOr(function (
        $query
    ) use ($user_id) {
        $query->where(['to_uid' => $user_id]);
    })->order('create_time desc')->value('create_time');
    
    return $create_time ? date('H:i:s', $create_time) : '';
}

/**
 * 获取用户的真实 IP
 * */
function getRealIp()
{
    if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
        $ip = $_SERVER['HTTP_CLIENT_IP'];
    } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
    } else {
        $ip = $_SERVER['REMOTE_ADDR'];
    }
    
    return $ip;
}

/**
 * 目录清单，列出所有文件和文件夹
 *
 * @param    string    $dir    路径
 * */
function list_files($dir)
{
    if (is_dir($dir)) {
        if ($handle = opendir($dir)) {
            while (($file = readdir($handle)) !== false) {
                if ($file != "." && $file != ".." && $file != "Thumbs.db"/*pesky windows, images..*/) {
                    echo '<a target="_blank" href="' . $dir . $file . '">' . $file . '</a>' . "\n";
                }
            }
            closedir($handle);
        }
    }
}

/**
 * 删除文件夹内容
 *
 * @param    string    $path    路径
 * */
function Delete($path)
{
    if (is_dir($path) === true) {
        $files = array_diff(scandir($path), array('.', '..'));
        foreach ($files as $file) {
            Delete(realpath($path) . '/' . $file);
        }
        
        return rmdir($path);
    } elseif (is_file($path) === true) {
        return unlink($path);
    }
    
    return false;
}

/**
 * 计算两个地图坐标之间的距离
 * */
function getDistanceBetweenPointsNew(
    $latitude1, $longitude1, $latitude2, $longitude2
) {
    $theta = $longitude1 - $longitude2;
    $miles = (sin(deg2rad($latitude1)) * sin(deg2rad($latitude2))) + (cos(deg2rad($latitude1)) * cos(deg2rad($latitude2)) * cos(deg2rad($theta)));
    $miles = acos($miles);
    $miles = rad2deg($miles);
    $miles = $miles * 60 * 1.1515;
    $feet = $miles * 5280;
    $yards = $feet / 3;
    $kilometers = $miles * 1.609344;
    $meters = $kilometers * 1000;
    
    return compact('miles', 'feet', 'yards', 'kilometers', 'meters');
}

/**
 * 转换字节
 *
 * @param    int    $bytes    传入字节数值
 * @param    int    $decimals
 *
 * @return string BKMGTP
 */
function human_filesize($bytes, $decimals = 2)
{
    $sz = 'BKMGTP';
    $factor = floor((strlen($bytes) - 1) / 3);
    
    return sprintf("%.{$decimals}f", $bytes / pow(1024, $factor)) . @$sz[$factor];
}

/**
 * 删除该目录以及该目录下面的所有文件和文件夹
 *
 * @param    string    $dir    目录
 *
 * @return bool
 */
function removeDir($dirName)
{
    //判断传入参数是否目录，如不是执行删除文件
    if (!is_dir($dirName)) {
        //删除文件
        @unlink($dirName);
    }
    //如果传入是目录，使用@opendir将该目录打开，将返回的句柄赋值给$handle
    $handle = @opendir($dirName);
    //这里明确地测试返回值是否全等于（值和类型都相同）FALSE
    //否则任何目录项的名称求值为 FALSE 的都会导致循环停止（例如一个目录名为“0”）
    while (($file = @readdir($handle)) !== false) {
        //在文件结构中，都会包含形如“.”和“..”的向上结构
        //但是它们不是文件或者文件夹
        if ($file != '.' && $file != '..') {
            //当前文件$dir为文件目录+文件
            $dir = $dirName . '/' . $file;
            //判断$dir是否为目录，如果是目录则递归调用reMoveDir($dirName)函数
            //将其中的文件和目录都删除；如果不是目录，则删除该文件
            is_dir($dir) ? removeDir($dir) : @unlink($dir);
        }
    }
    closedir($handle);
    
    return rmdir($dirName);
}

/**
 * curl获取网站状态码
 *
 * @param    string    $url    网址
 *
 * @return int
 * */
function curlGetCode($url)
{
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_TIMEOUT, 200);
    curl_setopt($ch, CURLOPT_HEADER, false);
    curl_setopt($ch, CURLOPT_NOBODY, false);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
    curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    
    return $httpCode;
}

/**
 * get_headers
 *
 * @param    string    $url    网址
 *
 * @return int
 * */
function headerGetCode($url)
{
    $url = str_replace('http://www.xntv.tv', 'https://www.xntv.tv', $url);
    
    $info = get_headers($url);
    $status_arr = explode(' ', $info['0']);
    
    return $status_arr[1];
}

/**
 * 网页错误描述内容
 *
 * @param    string    $url     网址
 * @param    int       $code    错误码
 *
 * @return string
 * */
function errorCodeDesc($url, $code)
{
    switch ($code) {
    case 100:
        $desc = 'Continue';
        break;
    case 101:
        $desc = 'Switching Protocols';
        break;
    case 200:
        $desc = 'OK';
        break;
    case 201:
        $desc = 'Created';
        break;
    case 202:
        $desc = 'Accepted';
        break;
    case 203:
        $desc = 'Non-Authoritative Information';
        break;
    case 204:
        $desc = 'No Content';
        break;
    case 205:
        $desc = 'Reset Content';
        break;
    case 206:
        $desc = 'Partial Content';
        break;
    case 300:
        $desc = 'Multiple Choices';
        break;
    case 301:
        $desc = 'Moved Permanently';
        break;
    case 302:
        $desc = 'Found';
        break;
    case 303:
        $desc = 'See Other';
        break;
    case 304:
        $desc = 'Not Modified';
        break;
    case 305:
        $desc = 'Use Proxy';
        break;
    case 306:
        $desc = 'Unused';
        break;
    case 307:
        $desc = 'Temporary Redirect';
        break;
    case 400:
        $desc = 'Unused';
        break;
    case 401:
        $desc = 'Unauthorized';
        break;
    case 402:
        $desc = 'Payment Required';
        break;
    case 403:
        $desc = 'Forbidden';
        break;
    case 404:
        $desc = 'Not Found';
        break;
    case 405:
        $desc = 'Method Not Allowed';
        break;
    case 406:
        $desc = 'Not Acceptable';
        break;
    case 407:
        $desc = 'Proxy Authentication Required';
        break;
    case 408:
        $desc = 'Request Time-out';
        break;
    case 409:
        $desc = 'Conflict';
        break;
    case 410:
        $desc = 'Gone';
        break;
    case 411:
        $desc = 'Length Required';
        break;
    case 412:
        $desc = 'Precondition Failed';
        break;
    case 413:
        $desc = 'Request Entity Too Large';
        break;
    case 414:
        $desc = 'Request-URI Too Large';
        break;
    case 415:
        $desc = 'Unsupported Media Type';
        break;
    case 416:
        $desc = 'Requested range not satisfiable';
        break;
    case 417:
        $desc = 'Expectation Failed';
        break;
    case 500:
        $desc = 'Internal Server Error';
        break;
    case 501:
        $desc = 'Not Implemented';
        break;
    case 502:
        $desc = 'Bad Gateway';
        break;
    case 503:
        $desc = 'Service Unavailable';
        break;
    case 504:
        $desc = 'Gateway Time-out';
        break;
    case 505:
        $desc = 'HTTP Version not supported';
        break;
    default:
        $desc = 'ERROR';
        break;
    }
    
    return date('Y-m-d H:i:s') . ' The abnormal value of “' . $url . '” was  “' . $desc . '”，please check for exceptions based on the URL of the content 。';
}

/**
 * 获取几天前的时间
 *
 * @param    int    $day    几天前
 *
 * @return string
 * */
function getAgoDate($day)
{
    return date("Y-m-d 00:00:00", strtotime("$day day"));
}

/**
 * 二维数组根据某个字段排序
 *
 * @param    array     $array    要排序的数组
 * @param    string    $keys     要排序的键字段
 * @param    string    $sort     排序类型  SORT_ASC     SORT_DESC
 *
 * @return array 排序后的数组
 */
function arraySort($array, $keys, $sort = SORT_DESC)
{
    $keysValue = [];
    foreach ($array as $k => $v) {
        $keysValue[$k] = $v[$keys];
    }
    array_multisort($keysValue, $sort, $array);
    
    return $array;
}

/**
 * 获取首页监测数据
 * */
function getCheckIndexData()
{
    $zero_time = strtotime(date('Y-m-d'));
    
    $list = Db::name('check_index_log')->field('id,status,check_time')->where(['check_time' => ['egt', $zero_time]])->order('id desc')->limit(12)->select();
    if ($list) {
        $list = arraySort($list, 'id', SORT_ASC);
        foreach ($list as &$v) {
            $v['check_date'] = date('H:i', $v['check_time']);
            $v['status'] = $v['status'] ?: -1;
        }
    }
    
    $check_date_arr = array_column($list, 'check_date');
    $status_arr = array_column($list, 'status');
    
    $data = [
        'check_date_arr' => $check_date_arr,
        'status_arr' => $status_arr,
        'all_count' => Db::name('check_index_log')->where(['check_time' => ['egt', $zero_time]])->count(),
        'error_count' => Db::name('check_index_log')->where(['check_time' => ['egt', $zero_time], 'status' => 0])->count()
    ];
    
    return json_encode($data, JSON_UNESCAPED_UNICODE);
}

/**
 * 获取新闻数据
 *
 * @param    int    $day    前几天
 *
 * @return array
 * */
function getNewData($day = 0)
{
    // 获取前几天的日期
    if ($day) {
        $start_date = getAgoDate('-' . $day);
        $publish_time_where['publish_time'] = ['egt', $start_date];
    }
    
    // 网页端新闻
    $web_error_count = 0;
    $web_today_news_count = 0;
    $web_list = Db::name('news')->field('id,url,title,status,publish_time')->where(['is_app' => 0])->where($publish_time_where)->order('publish_time desc')->select();
    if ($web_list) {
        foreach ($web_list as &$v) {
            $format_publish_time = date('m.d', strtotime($v['publish_time']));
            $v['format_publish_time'] = $format_publish_time;
            if ($format_publish_time == date('m.d')) ++$web_today_news_count;
            
            if ($v['status'] == 0) {
                ++$web_error_count;
                
                // 发生异常，查询最新的一条异常记录ID，用于后台点击跳转到异常详情
                $check_news_log_id = Db::name('check_news_log')->where(['news_id' => $v['id']])->max('id');
            }
            $v['check_news_log_id'] = $check_news_log_id ?: 0;
        }
    }
    // app端新闻
    $app_error_count = 0;
    $app_today_news_count = 0;
    $app_list = Db::name('news')->field('id,url,title,status,publish_time')->where(['is_app' => 1])->where($publish_time_where)->order('publish_time desc')->select();
    if ($app_list) {
        foreach ($app_list as &$v) {
            $format_publish_time = date('m.d', strtotime($v['publish_time']));
            $v['format_publish_time'] = $format_publish_time;
            if ($format_publish_time == date('m.d')) ++$app_today_news_count;
            
            if ($v['status'] == 0) {
                ++$app_error_count;
                
                // 发生异常，查询最新的一条异常记录ID，用于后台点击跳转到异常详情
                $check_news_log_id = Db::name('check_news_log')->where(['news_id' => $v['id']])->max('id');
            }
            $v['check_news_log_id'] = $check_news_log_id ?: 0;
        }
    }
    
    $data = [
        'web_list' => $web_list,
        'app_list' => $app_list,
        'web_all_news_count' => count($web_list),
        'app_all_news_count' => count($app_list),
        'web_today_news_count' => $web_today_news_count,
        'app_today_news_count' => $app_today_news_count,
        'web_error_count' => $web_error_count,
        'app_error_count' => $app_error_count,
    ];
    
    return $data;
}

/**
 * 获取星期
 *
 * @param    string    $date    日期
 *
 * @return string
 * */
function getWeek($date)
{
    $week_array = array("日", "一", "二", "三", "四", "五", "六");
    
    return "星期" . $week_array[date("w", strtotime($date))];
}

/**
 * 获取 视频/音频 列表
 *
 * @param    int    $type    0：全部；1：视频，2：音频
 *
 * @return array
 * */
function getLiveSourceList($type = 0)
{
    $list = [];
    for ($i = -6; $i <= 0; $i++) {
        $start_date = getAgoDate($i);
        $end_date = str_replace('00:00:00', '23:59:59', $start_date);
        
        $where['publish_time'] = ['between', [$start_date, $end_date]];
        if ($type == 1) {
            $where['type_id'] = ['IN', '1,2'];
        } elseif ($type == 2) {
            $where['type_id'] = ['IN', '3,4,5,6'];
        }
        
        $all_count = Db::name('live')->where($where)->count();
        $all_error_count = Db::name('live')->where($where)->where(['status' => 0])->count();
        
        $list[] = [
            'date' => getWeek($start_date) . '（' . date('m-d', strtotime($start_date)) . '）',
            'all_count' => $all_count,
            'error_count' => $all_error_count
        ];
    }
    
    return $list;
}

/**
 * 获取视频数据
 * */
function getLiveVideoData()
{
    // 监测频率；单位（分钟）
    $check_frequency = cache('siren_config')['monitor_gap'];
    
    // 上次监测时间
    $prev_check_time = Db::name('check_live_log')->where(['type' => 1])->max('check_time');
    if ($prev_check_time) {
        $prev_check_date = date('H:i', $prev_check_time);
    } else {
        $prev_check_date = date('H:i');
    }
    
    // 下次监测时间
    $next_check_date = date('H:i', strtotime($prev_check_date) + $check_frequency * 60);
    
    $data = [
        'prev_check_date' => $prev_check_date,
        'next_check_date' => $next_check_date,
        'list' => getLiveSourceList(1),
    ];
    
    return $data;
}

/**
 * 获取音频数据
 * */
function getLiveMusicData()
{
    // 监测频率；单位（分钟）
    $check_frequency = cache('siren_config')['monitor_gap'];
    
    // 上次监测时间
    $prev_check_time = Db::name('check_live_log')->where(['type' => 2])->max('check_time');
    if ($prev_check_time) {
        $prev_check_date = date('H:i', $prev_check_time);
    } else {
        $prev_check_date = date('H:i');
    }
    
    // 下次监测时间
    $next_check_date = date('H:i', strtotime($prev_check_date) + $check_frequency * 60);
    
    $data = [
        'prev_check_date' => $prev_check_date,
        'next_check_date' => $next_check_date,
        'list' => getLiveSourceList(2),
    ];
    
    return $data;
}

/**
 * 获取实时预警数据
 * */
function getSirenData()
{
    $date = date('Y-m-d');
    // 当日总预警
    $all_error_count = Db::name('crontab_log')->where(['date' => $date, 'status' => 0])->count();
    if ($all_error_count) {
        // 当日未处理
        $all_not_do_count = Db::name('crontab_log')->where(['date' => $date, 'status' => 0, 'is_do' => 0])->count();
        // 首页预警次数
        $index_count = Db::name('crontab_log')->where(['date' => $date, 'status' => 0, 'type' => 1])->count();
        // 首页预警占比
        $index_rate = sprintf('%.2f', ($index_count / $all_error_count) * 100);
        // 新闻预警次数
        $news_count = Db::name('crontab_log')->where(['date' => $date, 'status' => 0, 'type' => 2])->count();
        // 新闻预警占比
        $news_rate = sprintf('%.2f', ($news_count / $all_error_count) * 100);
        // 视频预警次数
        $video_count = Db::name('crontab_log')->where(['date' => $date, 'status' => 0, 'type' => 3])->count();
        // 视频预警占比
        $video_rate = sprintf('%.2f', ($video_count / $all_error_count) * 100);
        // 音频预警次数
        $music_count = Db::name('crontab_log')->where(['date' => $date, 'status' => 0, 'type' => 4])->count();
        // 视频预警占比
        $music_rate = sprintf('%.2f', 100 - $index_rate - $news_rate - $video_rate);
    } else {
        $all_not_do_count = 0;
        $index_count = 0;
        $index_rate = 0;
        $news_count = 0;
        $news_rate = 0;
        $video_count = 0;
        $video_rate = 0;
        $music_count = 0;
        $music_rate = 0;
    }
    
    $data = [
        'all_error_count' => $all_error_count,
        'all_not_do_count' => $all_not_do_count,
        'index_count' => $index_count,
        'index_rate' => $index_rate,
        'news_count' => $news_count,
        'news_rate' => $news_rate,
        'video_count' => $video_count,
        'video_rate' => $video_rate,
        'music_count' => $music_count,
        'music_rate' => $music_rate
    ];
    
    return $data;
}

/**
 * 将秒进行格式化
 *
 * @param    int    $inputSeconds    秒数
 *
 * @return return
 */
function secondsToTime($inputSeconds)
{
    $secondsInAMinute = 60;
    $secondsInAnHour = 60 * $secondsInAMinute;
    $secondsInADay = 24 * $secondsInAnHour;
    
    // extract days
    $days = floor($inputSeconds / $secondsInADay);
    
    // extract hours
    $hourSeconds = $inputSeconds % $secondsInADay;
    $hours = floor($hourSeconds / $secondsInAnHour);
    
    // extract minutes
    $minuteSeconds = $hourSeconds % $secondsInAnHour;
    $minutes = floor($minuteSeconds / $secondsInAMinute);
    
    // extract the remaining seconds
    $remainingSeconds = $minuteSeconds % $secondsInAMinute;
    $seconds = ceil($remainingSeconds);
    
    return ($days ? $days . '天' : '') . ($hours ? $hours . '小时' : '') . ($minutes ? $minutes . '分钟' : '') . ($seconds ? $seconds . '秒' : '');
}

/**
 * 异常持续时间（分钟）
 *
 * @param    int    $type              1：首页，2：新闻，3：音视频
 * @param    int    $course_id         资源id
 * @param    int    $log_id            记录id
 * @param    int    $end_check_time    最新的监测时间，也就是$log_id对应的时间
 * @param    int    $keep_time         持续时间秒数
 *
 * @return string
 * */
function errorKeepTime($type, $course_id, $log_id, $end_check_time, $keep_time = '')
{
    if ($type == 1) {
        $check_info = Db::name('check_index_log')->field('id,check_time,status')->where(['id' => ['lt', $log_id]])->order('id desc')->find();
    } elseif ($type == 2) {
        $check_info = Db::name('check_news_log')->field('id,check_time,status')->where(['news_id' => $course_id, 'id' => ['lt', $log_id]])->order('id desc')->find();
    } elseif ($type == 3) {
        $check_info = Db::name('check_live_log')->field('id,check_time,status')->where(['live_id' => $course_id, 'id' => ['lt', $log_id]])->order('id desc')->find();
    }
    
    if ($last_check_time = $check_info['check_time']) {
        if ($check_info['status'] == 0) {
            $keep_time += $end_check_time - $last_check_time;
            
            return errorKeepTime($type, $course_id, $check_info['id'], $last_check_time, $keep_time);
        } else {
            return secondsToTime($keep_time + floor(($end_check_time - $last_check_time)));
        }
    } else {
        return secondsToTime($keep_time);
    }
}

/**
 * 获取监测配置
 * */
function getSirenConfig()
{
    $siren_config = cache('siren_config');
    if (empty($siren_config)) {
        $siren_config = Db::name('siren_config')->find();
        $siren_time_gap = getSirenTimeGap($siren_config);
        $siren_config['siren_time_gap'] = $siren_time_gap;
        
        cache('siren_config', $siren_config);
    }
    
    return $siren_config;
}

/**
 * 获取监测时间间隔
 *
 * @param    array    $siren_config    监测基本配置
 *
 * @return array
 * */
function getSirenTimeGap($siren_config)
{
    if ($siren_config) {
        $basics_gap = $siren_config['basics_gap'];// 报警间隔（分钟）   10
        $max_gap = $siren_config['max_gap'];//顶峰报警时间间隔（分钟）  60
        $max_siren_count = $siren_config['max_siren_count'];// 顶峰报警次数
        $siren_time_gap = [];
        for ($i = $basics_gap; $i <= $max_gap; $i = !$siren_time_gap[0] ? $basics_gap : $siren_time_gap[count($siren_time_gap) - 1] * 2) {
            $siren_time_gap[] = $i;
        }
        if ($siren_time_gap) {
            $count = (max($siren_time_gap) < $max_gap) ? $max_siren_count + 1 : $max_siren_count;
            for ($j = 0; $j < $count; $j++) {
                $siren_time_gap[] = $max_gap;
            }
        }
        
        return $siren_time_gap;
    } else {
        return [];
    }
}

/**
 * 检测是否为手机
 *
 * @param    string    $phone    验证手机号
 *
 * @return boolean
 */
function isTel($phone)
{
    if (strlen($phone) != 11 || !preg_match('/^0?(13[0-9]|14[5-9]|15[012356789]|166|17[0-8]|18[0-9]|19[8-9])[0-9]{8}$/', $phone)) {
        return false;
    } else {
        return true;
    }
}

/**
 * 发送短信
 *
 * @param    string    $mobile    手机号
 * @param    int       $type      1：首页，2：新闻，3：视频，4：音频，5：网站当日新闻没有更新
 * @param    int       $is_app    是否是app端；0：否，1：是
 * */
function sendSms($mobile, $type, $is_app = false)
{
    switch ($type) {
    case 1:
        $msg = '首页无法访问，请及时处理';
        break;
    case 2:
        $msg = ($is_app ? 'app' : '网站') . '新闻无法访问，请及时处理';
        break;
    case 3:
        $msg = ($is_app ? 'app' : '网站') . '视频无法访问，请及时处理';
        break;
    case 4:
        $msg = ($is_app ? 'app' : '网站') . '音频无法访问，请及时处理';
        break;
    case 5:
        $msg = '网站当日新闻没有更新，请及时发布';
        break;
    }
    
    if ($mobile && $msg) {
        $smsapi = "http://api.smsbao.com/";
        $user = C('WEB_SMS_ACC'); //短信平台帐号
        $pass = md5(C('WEB_SMS_PWD')); //短信平台密码
        $content = "【监测宝】" . $msg;//要发送的短信内容
        $sendurl = $smsapi . "sms?u=" . $user . "&p=" . $pass . "&m=" . $mobile . "&c=" . urlencode($content);
        file_get_contents($sendurl);
    }
}